package org.datascooter.bundle.attribute;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.util.logging.Logger;

import org.datascooter.utils.LangUtils;

/**
 * This class purposed for mapping a persisted child objects. This objects, contained in parent in runtime and will be persisted with parent and tables may be linked with references
 * 
 * @author nemo
 * 
 */
public class PersistChildMethodAttribute extends PersistChildAttribute {

	private Method getter;
	private Method setter;

	public PersistChildMethodAttribute(String name, String entity, String mapKeyAttribute, PersistencePolicy policy, boolean embedded, boolean fetchLazy, String joinAttribute, Boolean joinFromChild) {
		super(name, entity, mapKeyAttribute, policy, embedded, fetchLazy, joinAttribute, joinFromChild);
	}

	@Override
	public void explore(Class<?> clazz) {
		try {
			super.explore(clazz);
		} catch (SecurityException e1) {
			e1.printStackTrace();
		} catch (NoSuchMethodException e1) {
			e1.printStackTrace();
		}
		if (clazz != null) {
			try {
				if (name.startsWith(GET)) {
					getter = clazz.getMethod(name);
				} else {
					getter = clazz.getMethod(GET + LangUtils.capitalize(name));
				}
				setGetClass(getter.getReturnType());
			} catch (Exception e) {
				Logger.getLogger(this.getClass().getName()).severe("*** Add Container Attribute -  provide getter:" + e.getMessage());
				setPolicy(PersistencePolicy.INSERT);
			}
			try {
				if (name.startsWith(SET)) {
					setter = clazz.getMethod(name, new Class[] {
						getClass
					});
				} else {
					setter = clazz.getMethod(SET + LangUtils.capitalize(name), new Class[] {
						getClass
					});
				}
			} catch (Exception e) {
				Logger.getLogger(this.getClass().getName()).severe("*** Add Container Attribute -  provide setter:" + e.getMessage());
				setPolicy(PersistencePolicy.SELECT);
			}
			returnType = getter.getReturnType();
			setGetClass(returnType);
			setSetClass(returnType);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> Object getValue(Object obj) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		return (T) getter.invoke(obj);
	}

	@Override
	public void setValue(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException, ParseException {
		setter.invoke(obj, value);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T extends AbstractAttribute> T copy() {
		return (T) new PersistChildMethodAttribute(name, entity, mapKeyAttribute, policy, embedded, fetchLazy, joinAttribute, joinFromChild);
	}
}
